package com.ys.filelib.filedialog;

import android.content.Context;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.Toast;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.ys.filelib.R;
import com.ys.filelib.databinding.FilelibLayoutStorageBinding;
import com.ys.filelib.filedialog.adapter.FileListAdapter;
import com.ys.filelib.filedialog.adapter.FilePathsAdapter;
import com.ys.filelib.filedialog.adapter.StorageAdapter;
import com.ys.filelib.filedialog.adapter.base.BaseQuickAdapter;
import com.ys.filelib.filedialog.adapter.base.BaseViewHolder;
import com.ys.filelib.filedialog.adapter.base.QuickAdapter;
import com.ys.filelib.filedialog.adapter.base.listener.OnItemClickListener;
import com.ys.filelib.filedialog.common.IDownloadListener;
import com.ys.filelib.filedialog.config.FileSelectConfig;
import com.ys.filelib.filedialog.ftp.FTPDriveHelper;
import com.ys.filelib.filedialog.ftp.FTPService;
import com.ys.filelib.filedialog.loader.FileLoader;
import com.ys.filelib.filedialog.loader.RemoteDiskDao;
import com.ys.filelib.filedialog.view.AdapterUpdateView;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * 文件存储dialog
 */
public class StorageDialog extends MyDialog {
    static String YUN_TEMP_DIR = FileUtil.sLocalRoot + "/emeeting/yunpan/temp";
    private FilelibLayoutStorageBinding mView;
    private FileListAdapter mFileAdapter;
    private StorageAdapter mStorageAdapter;
    private FilePathsAdapter mPathAdapter;

    private final FileDataModel mFileModel;
    private Callback<List<FileInfo>> mListCallback;
    private Callback<SparseArray<List<StorageItem>>> mStorageCallback;

    private OnSelectFileListener mSelectListener;
    private StorageItem mCurrentStorage;
    private final List<FileInfo> mDownloadList = new ArrayList<>();

    private StorageReceiver mStoreReceiver;
    private TipProgressDialog mTipProgressDialog;
    private final Set<Integer> mTypeSet = new HashSet<>();
    private final Set<Integer> mDiskTypeSet = new LinkedHashSet<>();
    private final List<String> mSelectFilesStr = new ArrayList<>();
    private final List<Integer> mIndexList = new ArrayList<>();
    private int mSpanCount = 5;

    public StorageDialog(Context context) {
        super(context);
        StorageUtils.init(context);
        mFileModel = new FileDataModel(context);
        mStoreReceiver = new StorageReceiver();
        mView = FilelibLayoutStorageBinding.inflate(getInflater());
    }

    @Override
    protected View getView() {
        initVew();
        return mView.getRoot();
    }

    private void initVew() {
        initAdapter();
        initListener();
        initSelectView();
        // 文件列表回调
        mListCallback = new Callback<List<FileInfo>>() {
            @Override
            public void onNext(List<FileInfo> fileList) {
                logFileList("文件个数=" + fileList.size());
                FileLoader.dispose();
                mFileAdapter.setNewData(fileList);
                mView.pbBar.setVisibility(View.GONE);
                mView.llEmpty.setVisibility(fileList.size() > 0 ? View.GONE : View.VISIBLE);
            }
        };

        // 磁盘列表回调
        mStorageCallback = new Callback<SparseArray<List<StorageItem>>>() {
            @Override
            public void onNext(SparseArray<List<StorageItem>> array) {
                List<StorageItem> list = array.get(StorageItem.TYPE_INNER);
                if (mDiskTypeSet.isEmpty()) {
                    list = array.get(StorageItem.TYPE_ALL);
                    list.add(null);
                } else {
                    for (int type : mDiskTypeSet) {
                        if (type != StorageItem.TYPE_INNER) {
                            List<StorageItem> typeList = array.get(type);
                            if (typeList != null) {
                                list.addAll(typeList);
                            }
                        }
                    }
                    if (mDiskTypeSet.contains(StorageItem.TYPE_FTP)) {
                        list.add(null);
                    }
                }
                mStorageAdapter.setNewData(list);
                if (list.size() > 0) {
                    showStorageRoot(list.get(0));
                }
            }
        };

        // 外部磁盘插拔监听
        mStoreReceiver.setStateListener(new StorageReceiver.OnStateListener() {
            @Override
            public void onStorageIn(String path) {
                if (!mDiskTypeSet.isEmpty() && !mDiskTypeSet.contains(StorageItem.TYPE_USB)) {
                    return;
                }
                StorageItem item = mFileModel.getStorageItemByPath(path);
                if (mStorageAdapter.getItemCount() < 1) {
                    showStorageRoot(item);
                }
                mStorageAdapter.addData(mStorageAdapter.getItemCount() > 0 ? 1 : 0, item);
            }

            @Override
            public void onStorageOut(String path) {
                if (mCurrentStorage == null) {
                    return;
                }
                if (path.equals(mCurrentStorage.path)) {
                    mStorageAdapter.remove(mCurrentStorage);
                    if (mStorageAdapter.getItemCount() > 0) {
                        showStorageRoot(mStorageAdapter.getItem(0));
                    }
                    return;
                }
                for (StorageItem item : mStorageAdapter.getData()) {
                    if (path.equals(item.path)) {
                        mStorageAdapter.remove(item);
                        break;
                    }
                }
            }
        });
    }

    QuickAdapter<FileInfo> selectAdapter;

    private void initSelectView() {
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        linearLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
        mView.recySelect.setLayoutManager(linearLayoutManager);
        selectAdapter = new QuickAdapter<FileInfo>(R.layout.filelib_item_select_dialog_view) {
            @Override
            protected void convert(BaseViewHolder holder, FileInfo item) {
                AdapterUpdateView.updateViewInfo(getContext(), holder, item.getPath());
            }
        };
        mView.recySelect.setAdapter(selectAdapter);

        selectAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter<?, ?> baseAdapter, View view, int position) {
                selectAdapter.remove(position);
                mView.tvSelectNum.setText(getContext().getString(R.string.current_select_title) + ": " + selectAdapter.getItemCount());
            }
        });

        mView.tvSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (selectAdapter.getData().isEmpty()) {
                    Toast.makeText(getContext(), R.string.no_select_file, Toast.LENGTH_SHORT).show();
                    return;
                }
                int index = 0;
                mIndexList.clear();
                mDownloadList.clear();
                mSelectFilesStr.clear();
                for (FileInfo item : selectAdapter.getData()) {
                    mSelectFilesStr.add(item.getPath());
                    if (item.ftpFile != null) {
                        mDownloadList.add(item);
                        mIndexList.add(index);
                    }
                    index++;
                }
                if (mSelectListener != null) {
                    if (mDownloadList.isEmpty()) {
                        dismiss();
                        mSelectListener.onSelectBackList(new ArrayList<>(mSelectFilesStr));
                    } else {
                        startDownloadFromFTP(mDownloadList);
                    }
                }
            }
        });
    }


    private void logFileList(String desc) {
        Log.e("cdl", "logFileList=" + desc);
    }

    private void initListener() {
        View.OnClickListener listener = v -> {
            if (v == mView.ivClose) {
                dismiss();
            }
            if (v == mView.ivList) {
                //列表显示
                mFileAdapter.setShowStyle(FileShowStyle.STYLE_LIST);
                mView.rvRight.setLayoutManager(new LinearLayoutManager(getContext()));
            }
            if (v == mView.ivGrid) {
                //网格显示
                mFileAdapter.setShowStyle(FileShowStyle.STYLE_GRID);
                mView.rvRight.setLayoutManager(new GridLayoutManager(getContext(), mSpanCount));
            }
            if (v == mView.typeImg) {
                //图片类型
                listFile(FileType.FILE_IMAGE);
            }
            if (v == mView.typeAudio) {
                //音频类型
                listFile(FileType.FILE_AUDIO);
            }
            if (v == mView.typeVideo) {
                //视频类型
                listFile(FileType.FILE_VIDEO);
            }
            if (v == mView.typeOffice) {
                //Office类型
                listFile(FileType.FILE_OFFICE);
            }
        };
        mView.ivClose.setOnClickListener(listener);
        mView.ivList.setOnClickListener(listener);
        mView.ivGrid.setOnClickListener(listener);
        mView.typeImg.setOnClickListener(listener);
        mView.typeAudio.setOnClickListener(listener);
        mView.typeVideo.setOnClickListener(listener);
        mView.typeOffice.setOnClickListener(listener);
    }

    private void initAdapter() {
        // 路径适配器
        mPathAdapter = new FilePathsAdapter();
        mPathAdapter.setOnItemClickListener((base, view, position) -> {
            if (position < 0) {
                return;
            }
            FilePath item = mPathAdapter.getItem(position);
            List<FilePath> list = mPathAdapter.getData();
            if (position + 1 != list.size()) {
                int count = list.size() - position - 1;
                while (count > 0) {
                    count--;
                    list.remove(list.size() - 1);
                }
                mPathAdapter.notifyDataSetChanged();
            }
            listDirFile(item.path);
        });
        mView.rvPaths.setAdapter(mPathAdapter);
        mView.rvPaths.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));

        // 磁盘适配器
        mStorageAdapter = new StorageAdapter();
        mStorageAdapter.setOnItemClickListener((base, view, position) -> {
            StorageItem storage = mStorageAdapter.getItem(position);
            if (storage == null) {
                showLoginFTP();
                return;
            }
            for (StorageItem item : mStorageAdapter.getData()) {
                if (item != null) {
                    item.check = false;
                }
            }
            showStorageRoot(storage);
        });

        //点击删除图标
        mStorageAdapter.setOnItemChildClickListener((base, view, position) -> {
            StorageItem item = mStorageAdapter.getItem(position);
            TipDialog dialog = new TipDialog(getContext());
            dialog.setContent(getContext().getString(R.string.str_delete_tip) + "\n" + item.name + "\n" + item.username);
            dialog.setOnSureListener(v -> {
                dialog.dismiss();
                RemoteDiskDao.deleteDriveUser(getContext(), item.type, item.host, item.port, item.username, item.email);
                mStorageAdapter.remove(position);
                Iterator<FileInfo> tor = selectAdapter.getData().iterator();
                while (tor.hasNext()) {
                    FileInfo next = tor.next();
                    if (next.ftpFile != null) {
                        tor.remove();
                    }
                }
                selectAdapter.notifyDataChanged();
                mView.tvSelectNum.setText(getContext().getString(R.string.current_select_title) + ": " + selectAdapter.getItemCount());
                if (item.check) {
                    StorageItem storage = mStorageAdapter.getItem(0);
                    if (storage != null) {
                        showStorageRoot(storage);
                    }
                }
            });
            dialog.show();
        });
        mStorageAdapter.addChildClickViewId(R.id.v_remove);
        mView.rvLeft.setLayoutManager(new LinearLayoutManager(getContext()));
        mView.rvLeft.setAdapter(mStorageAdapter);

        // 文件列表适配器
        mFileAdapter = new FileListAdapter(getContext());
        mFileAdapter.setOnItemClickListener((baseAdapter, view, position) -> {
            FileInfo fileInfo = mFileAdapter.getItem(position);
            if (fileInfo == null) {
                return;
            }
            if (fileInfo.isDirectory()) {
                //打开文件夹
                listDirFile(fileInfo.getPath());
                mPathAdapter.addData(new FilePath(fileInfo.getName(), fileInfo.getPath()));
                return;
            }

            //单选
            if (current_model_select == FileSelectConfig.MODEL_SELECT_ONLE) {
                if (fileInfo.ftpFile != null) {
                    mIndexList.clear();
                    mDownloadList.clear();
                    mDownloadList.add(fileInfo);
                    startDownloadFromFTP(mDownloadList);
                    return;
                }
                dismiss();
                if (mSelectListener != null) {
                    mSelectListener.onSelect(fileInfo.file, FileUtil.getFileType(fileInfo.getName()));
                }
                return;
            }
            //多选
            selectAdapter.addData(fileInfo);
            mView.tvSelectNum.setText(getContext().getString(R.string.current_select_title) + ": " + selectAdapter.getItemCount());
        });
        mView.rvRight.setLayoutManager(new GridLayoutManager(getContext(), mSpanCount));
        mView.rvRight.setAdapter(mFileAdapter);
    }

    /**
     * 显示FTP登陆窗口
     */
    private void showLoginFTP() {
        LoginFTPDialog loginFTP = new LoginFTPDialog(getContext());
        loginFTP.setFTPListener(helper -> {
            RemoteDiskDao.DriveUser user = RemoteDiskDao.create(helper);
            String name = user.ip + ":" + user.port;
            for (StorageItem item : mStorageAdapter.getData()) {
                if (item != null && name.equals(item.name) && user.name.equals(item.username)
                    && item.type == RemoteDiskDao.TYPE_FTP) {
                    return;
                }
            }
            FTPService.setFTPHelper(helper);
            RemoteDiskDao.insertDriveUser(getContext(), user);
            int count = mStorageAdapter.getItemCount();
            mStorageAdapter.addData(count > 0 ? (count - 1) : count, FileDataModel.driveUserToStorageItem(user));
        });
        loginFTP.show();
    }

    /**
     * 从FTP服务器下载文件
     */
    private void startDownloadFromFTP(List<FileInfo> list) {
        if (list.size() > 0) {
            FileInfo item = list.remove(0);
            FTPDriveHelper helper = FTPService.getFTPHelper(item.ftpFile.host, item.ftpFile.port, item.ftpFile.username);
            TipProgressDialog dialog = getTipProgressDialog();
            dialog.setProgress(0);
            dialog.setCancelListener(helper::stopDownload);
            dialog.setContent(item.getName());
            dialog.show();
            helper.downloadFile(item.ftpFile, getYunTempDir(), mDownloadListener);
        }
    }

    private final IDownloadListener mDownloadListener = new IDownloadListener() {
        @Override
        public void onSuccess(String filePath) {
            runOnUI(() -> {
                if (mSelectListener == null) {
                    return;
                }
                if (current_model_select == FileSelectConfig.MODEL_SELECT_ONLE) {
                    getTipProgressDialog().dismiss();
                    dismiss();
                    mSelectListener.onSelect(new File(filePath), FileUtil.getFileType(filePath));
                    return;
                }
                if (mIndexList.size() > 0) {
                    mSelectFilesStr.set(mIndexList.remove(0), filePath);
                }
                if (mDownloadList.isEmpty()) {
                    getTipProgressDialog().dismiss();
                    dismiss();
                    mSelectListener.onSelectBackList(new ArrayList<>(mSelectFilesStr));
                } else {
                    startDownloadFromFTP(mDownloadList);
                }
            });
        }

        @Override
        public void onProgress(long blockSize, int progress) {
            runOnUI(() -> getTipProgressDialog().setProgress(progress));
        }

        @Override
        public void onStop() {

        }

        @Override
        public void onFailure(Exception e) {
            runOnUI(() -> {
                getTipProgressDialog().dismiss();
                Toast.makeText(getContext(), "文件下载失败", Toast.LENGTH_SHORT).show();
            });
        }
    };

    /**
     * 显示类型文件
     */
    private void listFile(int fileType) {
        mFileAdapter.clear();
        mView.pbBar.setVisibility(View.VISIBLE);
        mFileModel.listDirFile(mCurrentStorage.path, fileType, mListCallback);
        mPathAdapter.clear();
        mPathAdapter.addData(new FilePath(mCurrentStorage.name, mCurrentStorage.path));
    }

    /**
     * 显示目录文件
     */
    private void listDirFile(String fileDir) {
        mFileAdapter.clear();
        mView.pbBar.setVisibility(View.VISIBLE);
        mFileModel.listDirFile(fileDir, mCurrentStorage, mTypeSet, mListCallback);
    }

    /**
     * 显示磁盘根目录文件
     */
    private void showStorageRoot(StorageItem item) {
        item.check = true;
        mPathAdapter.clear();
        mCurrentStorage = item;
        String showPath = mCurrentStorage.path;
        Log.e("cdl", "showPath=" + showPath);
        listDirFile(showPath);
        mPathAdapter.addData(new FilePath(mCurrentStorage.name, showPath));
        mStorageAdapter.notifyDataChanged();
        showTypeView(item.type == StorageItem.TYPE_INNER || item.type == StorageItem.TYPE_USB);
    }

    private void showTypeView(boolean show) {
        mView.typeImg.setVisibility(show && mTypeSet.contains(FileType.FILE_IMAGE) ? View.VISIBLE : View.GONE);
        mView.typeAudio.setVisibility(show && mTypeSet.contains(FileType.FILE_AUDIO) ? View.VISIBLE : View.GONE);
        mView.typeVideo.setVisibility(show && mTypeSet.contains(FileType.FILE_VIDEO) ? View.VISIBLE : View.GONE);
        mView.typeOffice.setVisibility(show && mTypeSet.contains(FileType.FILE_OFFICE) ? View.VISIBLE : View.GONE);
    }

    @Override
    protected void onStart() {
        selectAdapter.clear();
        mView.tvSelectNum.setText(getContext().getString(R.string.current_select_title) + ": 0");
        mFileModel.getLocalStorageList(mStorageCallback);
        mStoreReceiver.register(getContext());
        showTypeView(true);
    }

    @Override
    protected void onStop() {
        mStoreReceiver.unregister();
    }

    public void setTitle(String title) {
        mView.tvTitle.setText(title);
    }

    public int current_model_select = FileSelectConfig.MODEL_SELECT_ONLE;

    public void setSelectMode(int MODEL) {
        this.current_model_select = MODEL;
        if (current_model_select == FileSelectConfig.MODEL_SELECT_ONLE) {
            //单选
            mView.linSelectMoreLayout.setVisibility(View.GONE);
        } else {
            //多选
            mView.linSelectMoreLayout.setVisibility(View.VISIBLE);
        }
    }

    public void setFileType(int type) {
        mTypeSet.clear();
        mTypeSet.add(type);
    }

    public void addFileType(int type) {
        mTypeSet.add(type);
    }

    public void addDiskType(int type) {
        mDiskTypeSet.add(type);
    }

    public void clearDiskType() {
        mDiskTypeSet.clear();
    }

    public void setSpanCount(int spanCount) {
        this.mSpanCount = spanCount;
    }

    public void setOnSelectFileListener(OnSelectFileListener listener) {
        this.mSelectListener = listener;
    }

    private String getYunTempDir() {
        new File(YUN_TEMP_DIR).mkdirs();
        return YUN_TEMP_DIR;
    }

    public static void setYunTempDir(String tempDir) {
        if (tempDir != null) {
            YUN_TEMP_DIR = tempDir;
        }
    }

    public TipProgressDialog getTipProgressDialog() {
        if (mTipProgressDialog == null) {
            mTipProgressDialog = new TipProgressDialog(getContext());
        }
        return mTipProgressDialog;
    }

    public interface OnSelectFileListener {
        void onSelect(File file, int fileType);

        void onSelectBackList(List<String> fileList);
    }
}
